home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sprite 1984 - 1993
/
Sprite 1984 - 1993.iso
/
src
/
lib
/
c
/
etc
/
getpwent.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-11-27
|
7KB
|
306 lines
/*
* Copyright (c) 1988 The Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getpwent.c 5.9 (Berkeley) 4/1/89";
#endif /* LIBC_SCCS and not lint */
#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <pwd.h>
#include <ndbm.h>
static DBM *_pw_db;
static FILE *_pw_fp;
static struct passwd _pw_passwd;
static int _pw_rewind = 1, _pw_stayopen;
static char _pw_flag, *_pw_file = _PATH_PASSWD;
static int _pw_old = 0; /* 1 indicates old passwd file format. */
static start_pw(), scanpw(), fetch_pw(), getpw();
#define MAXLINELENGTH 1024
static char line[MAXLINELENGTH];
struct passwd *
getpwent()
{
datum key;
int rval;
if (!_pw_db && !_pw_fp && !start_pw())
return((struct passwd *)NULL);
do {
if (_pw_db) {
key.dptr = NULL;
rval = fetch_pw(key);
} else /* _pw_fp */
rval = scanpw();
} while (rval && (_pw_db && _pw_flag != _PW_KEYBYNAME));
if (rval)
getpw();
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
struct passwd *
getpwnam(nam)
char *nam;
{
int rval;
if (!start_pw())
return((struct passwd *)NULL);
if (_pw_db) {
datum key;
key.dptr = nam;
key.dsize = strlen(nam);
rval = fetch_pw(key);
} else /* _pw_fp */
for (rval = 0; scanpw();)
if (!strcmp(nam, _pw_passwd.pw_name)) {
rval = 1;
break;
}
if (!_pw_stayopen)
endpwent();
if (rval)
getpw();
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
struct passwd *
getpwuid(uid)
int uid;
{
int rval;
if (!start_pw())
return((struct passwd *)NULL);
if (_pw_db) {
datum key;
key.dptr = (char *)&uid;
key.dsize = sizeof(uid);
rval = fetch_pw(key);
} else /* _pw_fp */
for (rval = 0; scanpw();)
if (_pw_passwd.pw_uid == uid) {
rval = 1;
break;
}
if (!_pw_stayopen)
endpwent();
if (rval)
getpw();
return(rval ? &_pw_passwd : (struct passwd *)NULL);
}
static
start_pw()
{
char *p;
if (_pw_db) {
_pw_rewind = 1;
return(1);
}
if (_pw_fp) {
rewind(_pw_fp);
return(1);
}
if (_pw_db = dbm_open(_pw_file, O_RDONLY, 0))
return(1);
/*
* special case; if it's the official password file, look in
* the master password file, otherwise, look in the file itself.
* But, only look in the master file if we're root.
*/
if (!strcmp(_pw_file, _PATH_PASSWD)) {
if (geteuid()) {
p = _pw_file;
_pw_old = 1;
} else {
p = _PATH_MASTERPASSWD;
}
} else {
p = _pw_file;
}
if (_pw_fp = fopen(p, "r"))
return(1);
return(0);
}
setpwent()
{
return(setpassent(0));
}
setpassent(stayopen)
int stayopen;
{
if (!start_pw())
return(0);
_pw_stayopen = stayopen;
return(1);
}
void
endpwent()
{
if (_pw_db) {
dbm_close(_pw_db);
_pw_db = (DBM *)NULL;
} else if (_pw_fp) {
(void)fclose(_pw_fp);
_pw_fp = (FILE *)NULL;
}
}
void
setpwfile(file)
char *file;
{
_pw_file = file;
}
static
scanpw()
{
register char *cp;
long atol();
char *fgets(), *strsep(), *index();
for (;;) {
if (!(fgets(line, sizeof(line), _pw_fp)))
return(0);
/* skip lines that are too big */
if (!index(line, '\n')) {
int ch;
while ((ch = getc(_pw_fp)) != '\n' && ch != EOF)
;
continue;
}
_pw_passwd.pw_name = strsep(line, ":\n");
_pw_passwd.pw_passwd = strsep((char *)NULL, ":\n");
if (!(cp = strsep((char *)NULL, ":\n")))
continue;
_pw_passwd.pw_uid = atoi(cp);
if (!(cp = strsep((char *)NULL, ":\n")))
continue;
_pw_passwd.pw_gid = atoi(cp);
if (_pw_old) {
_pw_passwd.pw_class = "";
_pw_passwd.pw_change = 0;
_pw_passwd.pw_expire = 0;
} else {
_pw_passwd.pw_class = strsep((char *)NULL, ":\n");
if (!(cp = strsep((char *)NULL, ":\n")))
continue;
_pw_passwd.pw_change = atol(cp);
if (!(cp = strsep((char *)NULL, ":\n")))
continue;
_pw_passwd.pw_expire = atol(cp);
}
_pw_passwd.pw_gecos = strsep((char *)NULL, ":\n");
_pw_passwd.pw_dir = strsep((char *)NULL, ":\n");
_pw_passwd.pw_shell = strsep((char *)NULL, ":\n");
if (!_pw_passwd.pw_shell)
continue;
return(1);
}
/* NOTREACHED */
}
static
fetch_pw(key)
datum key;
{
register char *p, *t;
/*
* the .dir file is LOCK_EX locked by programs that are
* renaming the various password files.
*/
if (flock(dbm_dirfno(_pw_db), LOCK_SH))
return(0);
if (!key.dptr)
if (_pw_rewind) {
_pw_rewind = 0;
key = dbm_firstkey(_pw_db);
} else
key = dbm_nextkey(_pw_db);
if (key.dptr)
key = dbm_fetch(_pw_db, key);
(void)flock(dbm_dirfno(_pw_db), LOCK_UN);
if (!(p = key.dptr))
return(0);
t = line;
#define EXPAND(e) e = t; while (*t++ = *p++);
EXPAND(_pw_passwd.pw_name);
EXPAND(_pw_passwd.pw_passwd);
bcopy(p, (char *)&_pw_passwd.pw_uid, sizeof(int));
p += sizeof(int);
bcopy(p, (char *)&_pw_passwd.pw_gid, sizeof(int));
p += sizeof(int);
bcopy(p, (char *)&_pw_passwd.pw_change, sizeof(time_t));
p += sizeof(time_t);
EXPAND(_pw_passwd.pw_class);
EXPAND(_pw_passwd.pw_gecos);
EXPAND(_pw_passwd.pw_dir);
EXPAND(_pw_passwd.pw_shell);
bcopy(p, (char *)&_pw_passwd.pw_expire, sizeof(time_t));
p += sizeof(time_t);
_pw_flag = *p;
return(1);
}
static
getpw()
{
static char pwbuf[50];
off_t lseek();
long pos, atol();
int fd, n;
char *p;
if (!_pw_db || geteuid())
return;
/*
* special case; if it's the official password file, look in
* the master password file, otherwise, look in the file itself.
*/
p = strcmp(_pw_file, _PATH_PASSWD) ? _pw_file : _PATH_MASTERPASSWD;
if ((fd = open(p, O_RDONLY, 0)) < 0)
return;
pos = atol(_pw_passwd.pw_passwd);
if (lseek(fd, pos, L_SET) != pos)
goto bad;
if ((n = read(fd, pwbuf, sizeof(pwbuf) - 1)) < 0)
goto bad;
pwbuf[n] = '\0';
for (p = pwbuf; *p; ++p)
if (*p == ':') {
*p = '\0';
_pw_passwd.pw_passwd = pwbuf;
break;
}
bad: (void)close(fd);
}